dependent_var <- "MEDHVAL"
predictors <- c("PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES")
summary_stats <- data %>%
select(all_of(c(dependent_var, predictors))) %>%
summarise_all(list(Mean = mean, SD = sd), na.rm = TRUE) %>%
pivot_longer(cols = everything(), names_to = "Variable", values_to = "Value") %>%
separate(Variable, into = c("Variable", "Stat"), sep = "_") %>%
pivot_wider(names_from = Stat, values_from = Value)
summary_stats$Variable <- recode(summary_stats$Variable,
"MEDHVAL" = "Median House Value",
"NBELPOV100" = "# Households Living in Poverty",
"PCTBACHMOR" = "% of Individuals with Bachelor’s Degrees or Higher",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
)
summary_stats <- summary_stats %>%
mutate(
Mean = round(Mean, 2),
SD = round(SD, 2)
)
summary_stats <- summary_stats %>%
arrange(Variable == "Median House Value")
predictor_rows <- which(summary_stats$Variable != "Median House Value")
dependent_rows <- which(summary_stats$Variable == "Median House Value")
# Determine the start and end rows for each group
start_pred <- min(predictor_rows)
end_pred <- max(predictor_rows)
start_dep <- min(dependent_rows)
end_dep <- max(dependent_rows)
# Create the table using kable and add extra formatting
kable(summary_stats, caption = "Summary Statistics",
align = c("l", "l", "l"), booktabs = TRUE, escape = FALSE ) %>%
add_header_above(c(" " = 1, "Statistics" = 2)) %>%
kable_styling(full_width = FALSE) %>%
group_rows("Predictors", start_pred, end_pred) %>%
group_rows("Dependent Variable", start_dep, end_dep)%>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = TRUE)
Summary Statistics
|
|
Statistics
|
|
Variable
|
Mean
|
SD
|
|
Predictors
|
|
% of Individuals with Bachelor’s Degrees or Higher
|
16.08
|
17.77
|
|
# Households Living in Poverty
|
189.77
|
164.32
|
|
% of Vacant Houses
|
11.29
|
9.63
|
|
% of Single House Units
|
9.23
|
13.25
|
|
Dependent Variable
|
|
Median House Value
|
66287.73
|
60006.08
|
#check 0
columns_to_check <- c(dependent_var, predictors)
zero_counts <- sapply(data[columns_to_check], function(x) sum(x == 0, na.rm = TRUE))
zero_counts[zero_counts > 0]
## PCTBACHMOR NBELPOV100 PCTVACANT PCTSINGLES
## 143 33 163 306
data <- data %>%
mutate(
LNMEDHVAL = log(MEDHVAL),
LNPCTBACHMOR = log(1+PCTBACHMOR),
LNNBELPOV100 = log(1+NBELPOV100),
LNPCTVACANT = log(1+PCTVACANT),
LNPCTSINGLES = log(1+PCTSINGLES)
)
longer_version<- data %>%
pivot_longer(cols = c("MEDHVAL", "PCTBACHMOR", "NBELPOV100", "PCTVACANT", "PCTSINGLES"),
names_to = "Variable",
values_to = "Value")
ggplot(longer_version,aes(x = Value)) +
geom_histogram(aes(y = ..count..), fill = "blue", alpha = 0.7) +
facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
"MEDHVAL" = "Median House Value",
"PCTBACHMOR" = "% with Bachelor’s Degrees or Higher",
"NBELPOV100" = "# Households Living in Poverty",
"PCTVACANT" = "% of Vacant Houses",
"PCTSINGLES" = "% of Single House Units"
))) +
labs(x = "Value", y = "Count", title = "Histograms of Dependent and Predictor Variables") +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

# histograms of the transformed variables
longer_version2 <- data %>%
pivot_longer(cols = c(LNMEDHVAL, LNPCTBACHMOR ,LNNBELPOV100,LNPCTVACANT, LNPCTSINGLES),
names_to = "Variable",
values_to = "Value")
ggplot(longer_version2,aes(x = Value)) +
geom_histogram(aes(y = ..count..), fill = "red", alpha = 0.7) +
facet_wrap(~Variable, scales = "free", ncol = 3, labeller = as_labeller(c(
"LNMEDHVAL" = "Log Median House Value",
"LNPCTBACHMOR" = "Log % with Bachelor’s Degree",
"LNNBELPOV100" = "Log # Households in Poverty",
"LNPCTVACANT" = "Log % Vacant Houses",
"LNPCTSINGLES" = "Log % Single House Units"
))) +
labs(x = "Value", y = "Count", title = "Histograms of Dependent and log transformed Predictor Variables") +
theme_light() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

ggplot(shape) +
geom_sf(aes(fill = LNMEDHVAL), color = "transparent") +
scale_fill_gradientn(colors = c("#fff0f3", "#a4133c"),
name = "LNMEDHVAL",
na.value = "transparent") +
theme(legend.text = element_text(size = 9),
legend.title = element_text(size = 10),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)) +
labs(title = "Log Transformed Median House Value")

shpe_longer<- shape %>%
pivot_longer(cols = c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV"),
names_to = "Variable",
values_to = "Value")
custom_titles <- c(
PCTVACANT = "Percent of Vacant Houses",
PCTSINGLES = "Percent of Single House Units",
PCTBACHMOR = "Percent of Bachelor's Degree or Higher",
LNNBELPOV = "Logged Transformed Poverty Rate"
)
plot_list <- lapply(unique(shpe_longer$Variable), function(var_name) {
data_subset <- subset(shpe_longer, Variable == var_name)
ggplot(data_subset) +
geom_sf(aes(fill = Value), color = "transparent") +
scale_fill_gradientn(
colors = c("#fff0f3", "#a4133c"),
name = var_name,
na.value = "transparent"
) +
labs(title = custom_titles[[var_name]]) +
theme(
legend.text = element_text(size = 8),
legend.title = element_text(size = 10),
legend.key.size = unit(0.3, "cm"),
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 15, face = "bold"),
panel.background = element_blank(),
panel.border = element_rect(colour = "grey", fill = NA, size = 0.8)
)
})
# Combine the plots into a grid (2 columns by 2 rows)
combined_plot <- (plot_list[[1]] + plot_list[[2]]) /
(plot_list[[3]] + plot_list[[4]])
combined_plot

fit <- lm(LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR + LNNBELPOV100, data=data)
summary(fit)
##
## Call:
## lm(formula = LNMEDHVAL ~ PCTVACANT + PCTSINGLES + PCTBACHMOR +
## LNNBELPOV100, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.25825 -0.20391 0.03822 0.21744 2.24347
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 11.1137661 0.0465330 238.836 < 2e-16 ***
## PCTVACANT -0.0191569 0.0009779 -19.590 < 2e-16 ***
## PCTSINGLES 0.0029769 0.0007032 4.234 2.42e-05 ***
## PCTBACHMOR 0.0209098 0.0005432 38.494 < 2e-16 ***
## LNNBELPOV100 -0.0789054 0.0084569 -9.330 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3665 on 1715 degrees of freedom
## Multiple R-squared: 0.6623, Adjusted R-squared: 0.6615
## F-statistic: 840.9 on 4 and 1715 DF, p-value: < 2.2e-16
anova_table <- anova(fit)
anova_table
## Analysis of Variance Table
##
## Response: LNMEDHVAL
## Df Sum Sq Mean Sq F value Pr(>F)
## PCTVACANT 1 180.392 180.392 1343.087 < 2.2e-16 ***
## PCTSINGLES 1 24.543 24.543 182.734 < 2.2e-16 ***
## PCTBACHMOR 1 235.118 235.118 1750.551 < 2.2e-16 ***
## LNNBELPOV100 1 11.692 11.692 87.054 < 2.2e-16 ***
## Residuals 1715 230.344 0.134
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
fitted_values <- fitted(fit)
residuals_values <- residuals(fit)
standardized_residuals <- rstandard(fit)
data <- data %>%
mutate(
Fitted = fitted_values,
Residuals = residuals_values,
Standardized_Residuals = standardized_residuals)
ggplot(data, aes(x = Fitted, y = Standardized_Residuals)) +
geom_point(color = "black") +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
labs(
title = "Scatter Plot of Standardized Residuals vs Fitted Values",
x = "Predicted Values",
y = "Standardized Residuals"
) +
theme_minimal() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

ggplot(data, aes(x = Standardized_Residuals)) +
geom_histogram(bins = 30, fill = "black") +
labs(title = "Histogram of Standardized Residuals",
x = "Standardized Residuals",
y = "Frequency") +
theme_minimal() +
theme(plot.subtitle = element_text(size = 9,face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x=element_text(size=6),
axis.text.y=element_text(size=6),
axis.title=element_text(size=8))

#linear relationship
p1 <- ggplot(data, aes(x = PCTBACHMOR, y = MEDHVAL)) +
geom_point(alpha = 0.5, color = "blue") +
geom_smooth(method = "lm", se = FALSE, color = "red") +
ggtitle("% with Bachelor’s Degree vs. Median House Value") +
theme_minimal()
p2 <- ggplot(data, aes(x = NBELPOV100, y = MEDHVAL)) +
geom_point(alpha = 0.5, color = "blue") +
geom_smooth(method = "lm", se = FALSE, color = "red") +
ggtitle("# Households in Poverty vs. Median House Value") +
theme_minimal()
p3 <- ggplot(data, aes(x = PCTVACANT, y = MEDHVAL)) +
geom_point(alpha = 0.5, color = "blue") +
geom_smooth(method = "lm", se = FALSE, color = "red") +
ggtitle("% Vacant Houses vs. Median House Value") +
theme_minimal()
p4 <- ggplot(data, aes(x = PCTSINGLES, y = MEDHVAL)) +
geom_point(alpha = 0.5, color = "blue") +
geom_smooth(method = "lm", se = FALSE, color = "red") +
ggtitle("% Single House Units vs. Median House Value") +
theme_minimal()
grid.arrange(p1, p2, p3, p4, ncol = 2)
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'

custom_labels <- c(
"% of Individuals with Bachelor’s Degrees or Higher" = "PCTBACHMOR",
"% of Vacant Houses" = "PCTVACANT",
"% of Single House Units" = "PCTSINGLES",
"# Households Living in Poverty" = "LNNBELPOV100"
)
predictor_vars <- data[, c("PCTVACANT", "PCTSINGLES", "PCTBACHMOR", "LNNBELPOV100")]
cor_matrix <- cor(predictor_vars, use = "complete.obs", method = "pearson")
rownames(cor_matrix) <- names(custom_labels)
colnames(cor_matrix) <- names(custom_labels)
ggcorrplot(cor_matrix,
method = "square",
type = "lower",
lab = TRUE,
lab_size = 3,
colors = c("#d73027", "white", "#1a9850"))+
labs(title = "Correlation Matrix for all Predictor Variables") +
theme(plot.subtitle = element_text(size = 9, face = "italic"),
plot.title = element_text(size = 12, face = "bold"),
axis.text.x = element_text(size = 7),
axis.text.y = element_text(size = 7),
axis.title = element_text(size = 8))

LS0tCnRpdGxlOiAnVXNpbmcgT0xTIFJlZ3Jlc3Npb24gdG8gUHJlZGljdCBNZWRpYW4gSG91c2UgVmFsdWVzIGluIFBoaWxhZGVscGhpYScKYXV0aG9yOiAiWmhhbmNoYW8gWWFuZywgSGFveXUgWmh1LCBLYXZhbmEgUmFqdSIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogdW5pdGVkCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlkeWNlbnN1cykKbGlicmFyeShrbml0cikgCmxpYnJhcnkoZ3QpIApsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ2djb3JycGxvdCkKbGlicmFyeShwYXRjaHdvcmspCmBgYAoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGluY2x1ZGU9IEZBTFNFfQojIExvYWQgdGhlIGRhdGEKZGF0YSA8LSByZWFkLmNzdigiZGF0YS9SZWdyZXNzaW9uRGF0YS5jc3YiKQpzaGFwZSA8LSBzdF9yZWFkKCJkYXRhL1JlZ3Jlc3Npb25EYXRhLnNocCIpCmBgYAoKCmBgYHtyIHN1bW1hcnkgc3RhdHMsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmRlcGVuZGVudF92YXIgPC0gIk1FREhWQUwiCgpwcmVkaWN0b3JzIDwtIGMoIlBDVEJBQ0hNT1IiLCAiTkJFTFBPVjEwMCIsICJQQ1RWQUNBTlQiLCAiUENUU0lOR0xFUyIpCgpzdW1tYXJ5X3N0YXRzIDwtIGRhdGEgJT4lCiAgc2VsZWN0KGFsbF9vZihjKGRlcGVuZGVudF92YXIsIHByZWRpY3RvcnMpKSkgJT4lCiAgc3VtbWFyaXNlX2FsbChsaXN0KE1lYW4gPSBtZWFuLCBTRCA9IHNkKSwgbmEucm0gPSBUUlVFKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiVmFyaWFibGUiLCB2YWx1ZXNfdG8gPSAiVmFsdWUiKSAlPiUKICBzZXBhcmF0ZShWYXJpYWJsZSwgaW50byA9IGMoIlZhcmlhYmxlIiwgIlN0YXQiKSwgc2VwID0gIl8iKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gU3RhdCwgdmFsdWVzX2Zyb20gPSBWYWx1ZSkKCgoKc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSA8LSByZWNvZGUoc3VtbWFyeV9zdGF0cyRWYXJpYWJsZSwKICAiTUVESFZBTCIgPSAiTWVkaWFuIEhvdXNlIFZhbHVlIiwKICAiTkJFTFBPVjEwMCIgPSAiIyBIb3VzZWhvbGRzIExpdmluZyBpbiBQb3ZlcnR5IiwKICAiUENUQkFDSE1PUiIgPSAiJSBvZiBJbmRpdmlkdWFscyB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWVzIG9yIEhpZ2hlciIsCiAgIlBDVFZBQ0FOVCIgPSAiJSBvZiBWYWNhbnQgSG91c2VzIiwKICAiUENUU0lOR0xFUyIgPSAiJSBvZiBTaW5nbGUgSG91c2UgVW5pdHMiCikKCgoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIG11dGF0ZSgKICAgIE1lYW4gPSByb3VuZChNZWFuLCAyKSwKICAgIFNEID0gcm91bmQoU0QsIDIpCiAgKQoKc3VtbWFyeV9zdGF0cyA8LSBzdW1tYXJ5X3N0YXRzICU+JQogIGFycmFuZ2UoVmFyaWFibGUgPT0gIk1lZGlhbiBIb3VzZSBWYWx1ZSIpCgpwcmVkaWN0b3Jfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlICE9ICJNZWRpYW4gSG91c2UgVmFsdWUiKQpkZXBlbmRlbnRfcm93cyA8LSB3aGljaChzdW1tYXJ5X3N0YXRzJFZhcmlhYmxlID09ICJNZWRpYW4gSG91c2UgVmFsdWUiKQoKIyBEZXRlcm1pbmUgdGhlIHN0YXJ0IGFuZCBlbmQgcm93cyBmb3IgZWFjaCBncm91cApzdGFydF9wcmVkIDwtIG1pbihwcmVkaWN0b3Jfcm93cykKZW5kX3ByZWQgICA8LSBtYXgocHJlZGljdG9yX3Jvd3MpCnN0YXJ0X2RlcCAgPC0gbWluKGRlcGVuZGVudF9yb3dzKQplbmRfZGVwICAgIDwtIG1heChkZXBlbmRlbnRfcm93cykKCiMgQ3JlYXRlIHRoZSB0YWJsZSB1c2luZyBrYWJsZSBhbmQgYWRkIGV4dHJhIGZvcm1hdHRpbmcKa2FibGUoc3VtbWFyeV9zdGF0cywgY2FwdGlvbiA9ICJTdW1tYXJ5IFN0YXRpc3RpY3MiLCAKICAgICAgYWxpZ24gPSBjKCJsIiwgImwiLCAibCIpLCBib29rdGFicyA9IFRSVUUsIGVzY2FwZSA9IEZBTFNFICkgJT4lCiAgYWRkX2hlYWRlcl9hYm92ZShjKCIgIiA9IDEsICJTdGF0aXN0aWNzIiA9IDIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lCiAgZ3JvdXBfcm93cygiUHJlZGljdG9ycyIsIHN0YXJ0X3ByZWQsIGVuZF9wcmVkKSAlPiUKICBncm91cF9yb3dzKCJEZXBlbmRlbnQgVmFyaWFibGUiLCBzdGFydF9kZXAsIGVuZF9kZXApJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBUUlVFKQoKYGBgCgoKCmBgYHtyfQojY2hlY2sgMApjb2x1bW5zX3RvX2NoZWNrIDwtIGMoZGVwZW5kZW50X3ZhciwgcHJlZGljdG9ycykKCnplcm9fY291bnRzIDwtIHNhcHBseShkYXRhW2NvbHVtbnNfdG9fY2hlY2tdLCBmdW5jdGlvbih4KSBzdW0oeCA9PSAwLCBuYS5ybSA9IFRSVUUpKQoKemVyb19jb3VudHNbemVyb19jb3VudHMgPiAwXQoKYGBgCgpgYGB7cn0KZGF0YSA8LSBkYXRhICU+JQogIG11dGF0ZSgKICAgIExOTUVESFZBTCA9IGxvZyhNRURIVkFMKSwKICAgIExOUENUQkFDSE1PUiA9IGxvZygxK1BDVEJBQ0hNT1IpLAogICAgTE5OQkVMUE9WMTAwID0gbG9nKDErTkJFTFBPVjEwMCksCiAgICBMTlBDVFZBQ0FOVCA9IGxvZygxK1BDVFZBQ0FOVCksCiAgICBMTlBDVFNJTkdMRVMgPSBsb2coMStQQ1RTSU5HTEVTKQogICkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD03LCBmaWcud2lkdGg9OSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbG9uZ2VyX3ZlcnNpb248LSBkYXRhICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYygiTUVESFZBTCIsICJQQ1RCQUNITU9SIiwgIk5CRUxQT1YxMDAiLCAiUENUVkFDQU5UIiwgIlBDVFNJTkdMRVMiKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiVmFyaWFibGUiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiVmFsdWUiKQoKZ2dwbG90KGxvbmdlcl92ZXJzaW9uLGFlcyh4ID0gVmFsdWUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmNvdW50Li4pLCBmaWxsID0gImJsdWUiLCBhbHBoYSA9IDAuNykgKyAgCiAgZmFjZXRfd3JhcCh+VmFyaWFibGUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDMsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoYygKICAgICJNRURIVkFMIiA9ICJNZWRpYW4gSG91c2UgVmFsdWUiLAogICAgIlBDVEJBQ0hNT1IiID0gIiUgd2l0aCBCYWNoZWxvcuKAmXMgRGVncmVlcyBvciBIaWdoZXIiLAogICAgIk5CRUxQT1YxMDAiID0gIiMgSG91c2Vob2xkcyBMaXZpbmcgaW4gUG92ZXJ0eSIsCiAgICAiUENUVkFDQU5UIiA9ICIlIG9mIFZhY2FudCBIb3VzZXMiLAogICAgIlBDVFNJTkdMRVMiID0gIiUgb2YgU2luZ2xlIEhvdXNlIFVuaXRzIgogICkpKSArICAKICBsYWJzKHggPSAiVmFsdWUiLCB5ID0gIkNvdW50IiwgdGl0bGUgPSAiSGlzdG9ncmFtcyBvZiBEZXBlbmRlbnQgYW5kIFByZWRpY3RvciBWYXJpYWJsZXMiKSArCiAgdGhlbWVfbGlnaHQoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD05LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIGhpc3RvZ3JhbXMgb2YgdGhlIHRyYW5zZm9ybWVkIHZhcmlhYmxlcwpsb25nZXJfdmVyc2lvbjIgPC0gZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoTE5NRURIVkFMLCBMTlBDVEJBQ0hNT1IgLExOTkJFTFBPVjEwMCxMTlBDVFZBQ0FOVCwgTE5QQ1RTSU5HTEVTKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiVmFyaWFibGUiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiVmFsdWUiKQoKZ2dwbG90KGxvbmdlcl92ZXJzaW9uMixhZXMoeCA9IFZhbHVlKSkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5jb3VudC4uKSwgZmlsbCA9ICJyZWQiLCBhbHBoYSA9IDAuNykgKyAgCiAgZmFjZXRfd3JhcCh+VmFyaWFibGUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDMsIGxhYmVsbGVyID0gYXNfbGFiZWxsZXIoYygKICAgICJMTk1FREhWQUwiID0gIkxvZyBNZWRpYW4gSG91c2UgVmFsdWUiLAogICAgIkxOUENUQkFDSE1PUiIgPSAiTG9nICUgd2l0aCBCYWNoZWxvcuKAmXMgRGVncmVlIiwKICAgICJMTk5CRUxQT1YxMDAiID0gIkxvZyAjIEhvdXNlaG9sZHMgaW4gUG92ZXJ0eSIsCiAgICAiTE5QQ1RWQUNBTlQiID0gIkxvZyAlIFZhY2FudCBIb3VzZXMiLAogICAgIkxOUENUU0lOR0xFUyIgPSAiTG9nICUgU2luZ2xlIEhvdXNlIFVuaXRzIgogICkpKSArICAKICBsYWJzKHggPSAiVmFsdWUiLCB5ID0gIkNvdW50IiwgdGl0bGUgPSAiSGlzdG9ncmFtcyBvZiBEZXBlbmRlbnQgYW5kIGxvZyB0cmFuc2Zvcm1lZCBQcmVkaWN0b3IgVmFyaWFibGVzIikgKwogIHRoZW1lX2xpZ2h0KCkgKyAgIAogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksZmFjZSA9ICJpdGFsaWMiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksIAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTYpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTYpLCAKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTgpKQpgYGAKCgoKCmBgYHtyLGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTksd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZ2dwbG90KHNoYXBlKSArCiAgZ2VvbV9zZihhZXMoZmlsbCA9IExOTUVESFZBTCksIGNvbG9yID0gInRyYW5zcGFyZW50IikgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG9ycyA9IGMoIiNmZmYwZjMiLCAiI2E0MTMzYyIpLCAKICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkxOTUVESFZBTCIsIAogICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IikgKyAKICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiZ3JleSIsIGZpbGwgPSBOQSwgc2l6ZSA9IDAuOCkpICsKICBsYWJzKHRpdGxlID0gIkxvZyBUcmFuc2Zvcm1lZCBNZWRpYW4gSG91c2UgVmFsdWUiKQpgYGAKCgpgYGB7ciwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTE1LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpzaHBlX2xvbmdlcjwtIHNoYXBlICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYygiUENUVkFDQU5UIiwgIlBDVFNJTkdMRVMiLCAiUENUQkFDSE1PUiIsICJMTk5CRUxQT1YiKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiVmFyaWFibGUiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiVmFsdWUiKQpjdXN0b21fdGl0bGVzIDwtIGMoCiAgUENUVkFDQU5UICAgPSAiUGVyY2VudCBvZiBWYWNhbnQgSG91c2VzIiwKICBQQ1RTSU5HTEVTICA9ICJQZXJjZW50IG9mIFNpbmdsZSBIb3VzZSBVbml0cyIsCiAgUENUQkFDSE1PUiAgPSAiUGVyY2VudCBvZiBCYWNoZWxvcidzIERlZ3JlZSBvciBIaWdoZXIiLAogIExOTkJFTFBPViAgID0gIkxvZ2dlZCBUcmFuc2Zvcm1lZCBQb3ZlcnR5IFJhdGUiCikKCgoKcGxvdF9saXN0IDwtIGxhcHBseSh1bmlxdWUoc2hwZV9sb25nZXIkVmFyaWFibGUpLCBmdW5jdGlvbih2YXJfbmFtZSkgewogIGRhdGFfc3Vic2V0IDwtIHN1YnNldChzaHBlX2xvbmdlciwgVmFyaWFibGUgPT0gdmFyX25hbWUpCiAgCiAgZ2dwbG90KGRhdGFfc3Vic2V0KSArCiAgICBnZW9tX3NmKGFlcyhmaWxsID0gVmFsdWUpLCBjb2xvciA9ICJ0cmFuc3BhcmVudCIpICsKICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKAogICAgICBjb2xvcnMgPSBjKCIjZmZmMGYzIiwgIiNhNDEzM2MiKSwKICAgICAgbmFtZSA9IHZhcl9uYW1lLAogICAgICBuYS52YWx1ZSA9ICJ0cmFuc3BhcmVudCIKICAgICkgKwogICAgbGFicyh0aXRsZSA9IGN1c3RvbV90aXRsZXNbW3Zhcl9uYW1lXV0pICsKICAgIHRoZW1lKAogICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuMywgImNtIiksCiAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LCBmYWNlID0gImJvbGQiKSwKICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJncmV5IiwgZmlsbCA9IE5BLCBzaXplID0gMC44KQogICAgKQp9KQoKIyBDb21iaW5lIHRoZSBwbG90cyBpbnRvIGEgZ3JpZCAoMiBjb2x1bW5zIGJ5IDIgcm93cykKY29tYmluZWRfcGxvdCA8LSAocGxvdF9saXN0W1sxXV0gKyBwbG90X2xpc3RbWzJdXSkgLwogICAgICAgICAgICAgICAgIChwbG90X2xpc3RbWzNdXSArIHBsb3RfbGlzdFtbNF1dKQoKY29tYmluZWRfcGxvdApgYGAKCgpgYGB7ciByZWdyZXNzaW9ufQpmaXQgPC0gbG0oTE5NRURIVkFMIH4gUENUVkFDQU5UICsgUENUU0lOR0xFUyArIFBDVEJBQ0hNT1IgKyBMTk5CRUxQT1YxMDAsIGRhdGE9ZGF0YSkKc3VtbWFyeShmaXQpCmBgYApgYGB7cn0KYW5vdmFfdGFibGUgPC0gYW5vdmEoZml0KQphbm92YV90YWJsZQpgYGAKYGBge3J9CmZpdHRlZF92YWx1ZXMgPC0gZml0dGVkKGZpdCkKcmVzaWR1YWxzX3ZhbHVlcyA8LSByZXNpZHVhbHMoZml0KQpzdGFuZGFyZGl6ZWRfcmVzaWR1YWxzIDwtIHJzdGFuZGFyZChmaXQpCgpkYXRhIDwtIGRhdGEgJT4lCiAgbXV0YXRlKAogICAgRml0dGVkID0gZml0dGVkX3ZhbHVlcywKICAgIFJlc2lkdWFscyA9IHJlc2lkdWFsc192YWx1ZXMsCiAgICBTdGFuZGFyZGl6ZWRfUmVzaWR1YWxzID0gc3RhbmRhcmRpemVkX3Jlc2lkdWFscykKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGEsIGFlcyh4ID0gRml0dGVkLCB5ID0gU3RhbmRhcmRpemVkX1Jlc2lkdWFscykpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImJsYWNrIikgKyAgICAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiKSArICAKICBsYWJzKAogICAgdGl0bGUgPSAiU2NhdHRlciBQbG90IG9mIFN0YW5kYXJkaXplZCBSZXNpZHVhbHMgdnMgRml0dGVkIFZhbHVlcyIsCiAgICB4ID0gIlByZWRpY3RlZCBWYWx1ZXMiLAogICAgeSA9ICJTdGFuZGFyZGl6ZWQgUmVzaWR1YWxzIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArICAgCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSxmYWNlID0gIml0YWxpYyIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwgCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NiksIAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCkpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhLCBhZXMoeCA9IFN0YW5kYXJkaXplZF9SZXNpZHVhbHMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwLCBmaWxsID0gImJsYWNrIikgKwogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtIG9mIFN0YW5kYXJkaXplZCBSZXNpZHVhbHMiLCAKICAgICAgIHggPSAiU3RhbmRhcmRpemVkIFJlc2lkdWFscyIsIAogICAgICAgeSA9ICJGcmVxdWVuY3kiKSArCiAgdGhlbWVfbWluaW1hbCgpICsgICAKICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT02KSwgCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSkKYGBgCgoKCgoKCgoKCgoKCmBgYHtyfQojbGluZWFyIHJlbGF0aW9uc2hpcApwMSA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHggPSBQQ1RCQUNITU9SLCB5ID0gTUVESFZBTCkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSwgY29sb3IgPSAiYmx1ZSIpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKyAgCiAgZ2d0aXRsZSgiJSB3aXRoIEJhY2hlbG9y4oCZcyBEZWdyZWUgdnMuIE1lZGlhbiBIb3VzZSBWYWx1ZSIpICsKICB0aGVtZV9taW5pbWFsKCkKCnAyIDwtIGdncGxvdChkYXRhLCBhZXMoeCA9IE5CRUxQT1YxMDAsIHkgPSBNRURIVkFMKSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gMC41LCBjb2xvciA9ICJibHVlIikgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQiKSArICAKICBnZ3RpdGxlKCIjIEhvdXNlaG9sZHMgaW4gUG92ZXJ0eSB2cy4gTWVkaWFuIEhvdXNlIFZhbHVlIikgKwogIHRoZW1lX21pbmltYWwoKQoKcDMgPC0gZ2dwbG90KGRhdGEsIGFlcyh4ID0gUENUVkFDQU5ULCB5ID0gTUVESFZBTCkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSwgY29sb3IgPSAiYmx1ZSIpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKyAgCiAgZ2d0aXRsZSgiJSBWYWNhbnQgSG91c2VzIHZzLiBNZWRpYW4gSG91c2UgVmFsdWUiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpwNCA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHggPSBQQ1RTSU5HTEVTLCB5ID0gTUVESFZBTCkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSwgY29sb3IgPSAiYmx1ZSIpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkIikgKyAgCiAgZ2d0aXRsZSgiJSBTaW5nbGUgSG91c2UgVW5pdHMgdnMuIE1lZGlhbiBIb3VzZSBWYWx1ZSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmdyaWQuYXJyYW5nZShwMSwgcDIsIHAzLCBwNCwgbmNvbCA9IDIpCmBgYAoKCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKY3VzdG9tX2xhYmVscyA8LSBjKAogICIlIG9mIEluZGl2aWR1YWxzIHdpdGggQmFjaGVsb3LigJlzIERlZ3JlZXMgb3IgSGlnaGVyIiA9ICJQQ1RCQUNITU9SIiwKICAiJSBvZiBWYWNhbnQgSG91c2VzIiA9ICJQQ1RWQUNBTlQiLAogICIlIG9mIFNpbmdsZSBIb3VzZSBVbml0cyIgPSAiUENUU0lOR0xFUyIsCiAgIiMgSG91c2Vob2xkcyBMaXZpbmcgaW4gUG92ZXJ0eSIgPSAiTE5OQkVMUE9WMTAwIgopCgpwcmVkaWN0b3JfdmFycyA8LSBkYXRhWywgYygiUENUVkFDQU5UIiwgIlBDVFNJTkdMRVMiLCAiUENUQkFDSE1PUiIsICJMTk5CRUxQT1YxMDAiKV0KCmNvcl9tYXRyaXggPC0gY29yKHByZWRpY3Rvcl92YXJzLCB1c2UgPSAiY29tcGxldGUub2JzIiwgbWV0aG9kID0gInBlYXJzb24iKQpyb3duYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQpjb2xuYW1lcyhjb3JfbWF0cml4KSA8LSBuYW1lcyhjdXN0b21fbGFiZWxzKQoKCmdnY29ycnBsb3QoY29yX21hdHJpeCwgCiAgICAgICAgICAgbWV0aG9kID0gInNxdWFyZSIsICAgCiAgICAgICAgICAgdHlwZSA9ICJsb3dlciIsICAgICAgCiAgICAgICAgICAgbGFiID0gVFJVRSwgICAgICAgCiAgICAgICAgICAgbGFiX3NpemUgPSAzLCAgICAgIAogICAgICAgICAgIGNvbG9ycyA9IGMoIiNkNzMwMjciLCAid2hpdGUiLCAiIzFhOTg1MCIpKSsKICAgIGxhYnModGl0bGUgPSAiQ29ycmVsYXRpb24gTWF0cml4IGZvciBhbGwgUHJlZGljdG9yIFZhcmlhYmxlcyIpICsKICAgIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiaXRhbGljIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLCAKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKYGBgCgoKCg==